"""LLM Plays Pokemon 导航工具模块"""

import logging
from typing import Dict, Any, List, Optional, Tuple

from llm_pokemon.emulator.pyboy import PyBoyEmulator

logger = logging.getLogger(__name__)


class NavigatorTool:
    """导航工具类，提供navigator功能"""
    
    def __init__(self, config: Dict[str, Any], emulator_tool: PyBoyEmulator):
        """初始化导航工具
        
        Args:
            config: 导航工具配置
            emulator_tool: 模拟器工具实例
        """
        self.config = config
        self.emulator_tool = emulator_tool
        self.path_finding_algorithm = config["path_finding_algorithm"]
        self.max_path_length = config["max_path_length"]
        
        logger.info("导航工具初始化完成")
    
    def execute(self, target: Dict[str, Any]) -> Dict[str, Any]:
        """执行导航操作
        
        Args:
            target: 目标信息，可以是坐标、场景名称或特定操作
            
        Returns:
            导航结果
        """
        logger.info(f"执行导航操作: {target}")
        
        result = {
            "success": False,
            "message": "",
            "emulator_result": None
        }
        
        try:
            # 获取当前位置
            current_position = self._get_current_position()
            
            # 根据目标类型执行不同的导航逻辑
            if "coordinates" in target:
                # 导航到指定坐标
                target_x, target_y = target["coordinates"]
                path = self._find_path(current_position, (target_x, target_y))
                
                if not path:
                    result["message"] = f"无法找到从 {current_position} 到 ({target_x}, {target_y}) 的路径"
                    return result
                
                # 转换路径为按钮序列
                buttons = self._path_to_buttons(path)
                
                # 执行按钮序列
                emulator_result = self.emulator.execute(buttons)
                
                result["success"] = emulator_result["success"]
                result["message"] = f"导航到坐标 ({target_x}, {target_y}) {'成功' if result['success'] else '失败'}"
                result["emulator_result"] = emulator_result
                
            elif "scene" in target:
                # 导航到指定场景
                scene_name = target["scene"]
                scene_position = self._get_scene_position(scene_name)
                
                if not scene_position:
                    result["message"] = f"未知场景: {scene_name}"
                    return result
                
                # 递归调用自身，使用坐标导航
                return self.execute({"coordinates": scene_position})
                
            elif "action" in target:
                # 执行特定操作
                action = target["action"]
                buttons = self._action_to_buttons(action)
                
                if not buttons:
                    result["message"] = f"未知操作: {action}"
                    return result
                
                # 执行按钮序列
                emulator_result = self.emulator.execute(buttons)
                
                result["success"] = emulator_result["success"]
                result["message"] = f"执行操作 {action} {'成功' if result['success'] else '失败'}"
                result["emulator_result"] = emulator_result
                
            else:
                result["message"] = "无效的导航目标，需要提供坐标、场景或操作"
                
        except Exception as e:
            logger.error(f"导航操作失败: {e}")
            result["message"] = f"导航操作失败: {str(e)}"
            
        return result
    
    def _get_current_position(self) -> Tuple[int, int]:
        """获取当前位置
        
        Returns:
            当前坐标 (x, y)
        """
        # 这里需要实现获取当前位置的逻辑
        # 可以通过模拟器工具获取内存数据中的位置信息
        memory_data = self.emulator_tool._get_memory_data()
        return (memory_data["player_position"]["x"], memory_data["player_position"]["y"])
    
    def _find_path(self, start: Tuple[int, int], end: Tuple[int, int]) -> List[Tuple[int, int]]:
        """寻找从起点到终点的路径
        
        Args:
            start: 起点坐标 (x, y)
            end: 终点坐标 (x, y)
            
        Returns:
            路径点列表，如果无法到达则返回空列表
        """
        # 这里需要实现具体的寻路算法
        # 简化版本，实际实现需要更复杂的寻路逻辑
        
        # 检查路径长度是否超过最大限制
        if abs(end[0] - start[0]) + abs(end[1] - start[1]) > self.max_path_length:
            logger.warning(f"路径长度超过最大限制: {self.max_path_length}")
            return []
        
        # 简单的直线路径
        path = [start]
        
        # 先水平移动
        if start[0] != end[0]:
            path.append((end[0], start[1]))
        
        # 再垂直移动
        if start[1] != end[1]:
            path.append(end)
        
        return path
    
    def _path_to_buttons(self, path: List[Tuple[int, int]]) -> List[str]:
        """将路径转换为按钮序列
        
        Args:
            path: 路径点列表
            
        Returns:
            按钮序列
        """
        buttons = []
        
        for i in range(1, len(path)):
            prev = path[i-1]
            curr = path[i]
            
            # 水平移动
            if curr[0] > prev[0]:
                # 向右移动
                steps = curr[0] - prev[0]
                buttons.extend(["Right"] * steps)
            elif curr[0] < prev[0]:
                # 向左移动
                steps = prev[0] - curr[0]
                buttons.extend(["Left"] * steps)
            
            # 垂直移动
            if curr[1] > prev[1]:
                # 向下移动
                steps = curr[1] - prev[1]
                buttons.extend(["Down"] * steps)
            elif curr[1] < prev[1]:
                # 向上移动
                steps = prev[1] - curr[1]
                buttons.extend(["Up"] * steps)
        
        return buttons
    
    def _get_scene_position(self, scene_name: str) -> Optional[Tuple[int, int]]:
        """获取场景位置
        
        Args:
            scene_name: 场景名称
            
        Returns:
            场景坐标，如果不存在则返回None
        """
        # 这里需要实现场景名称到坐标的映射
        # 简化版本，实际实现需要更完整的场景数据
        scene_map = {
            "pallet_town": (10, 10),
            "viridian_city": (20, 20),
            "pewter_city": (30, 30),
            # 更多场景...
        }
        
        return scene_map.get(scene_name.lower())
    
    def _action_to_buttons(self, action: str) -> List[str]:
        """将操作转换为按钮序列
        
        Args:
            action: 操作名称
            
        Returns:
            按钮序列，如果不支持则返回空列表
        """
        # 这里需要实现操作名称到按钮序列的映射
        # 简化版本，实际实现需要更多的操作支持
        action_map = {
            "talk": ["A"],
            "open_menu": ["Start"],
            "select_pokemon": ["Start", "Down", "A"],
            "heal_pokemon": ["A", "A", "A", "A", "A", "A"],
            # 更多操作...
        }
        
        return action_map.get(action.lower(), [])